#!/usr/bin/env node

const _ = require('lodash');

function magicOddBase(list, n) {
    let result = [];
    let pos = Math.floor(n/2);
    _.forEach(list, o=>{
        result[pos] = o;
        const row = Math.floor(pos / n);
        const col = pos - row * n;
        let tr = row - 1;
        let tc = col + 1;
        if (tr < 0 && tc === n ) {
            tc = col;
            tr = row + 1;
        } else if (tr < 0) {
            tr = n - 1;
        } else if (tc === n) {
            tc = 0;
        } else if (result[tr * n + tc]) {
            tc = col;
            tr = row + 1;
        }
        pos = tr * n + tc;
    });
    return result;
}
function magicOdd(n) {
    const list = _.range(1, n*n+1);
    return magicOddBase(list, n);
}
function magic4nTimes(n) {
    const max = n*n+1;
    return _.map(_.range(1, max), (o, i)=>{
        const row = Math.floor(i / n);
        const col = i - row * n;
        if (!((row + col + 1) & 3)) {
            return max - o;
        }
        if (!((row - col) & 3)) {
            return max - o;
        }
        return o;
    });
}
function swap(list1, list2, pos) {
    const t = list1[pos];
    list1[pos] = list2[pos];
    list2[pos] = t;
}
function magic4n2Times(n) {
    const k = ( n - 2 ) / 4;
    const nn = n / 2;
    const nn2 = nn * nn;

    //分为四个象限
    const sublists = [[],[],[],[]];
    for (let i = 0; i < nn2; i++) {
        sublists[0][i] = i+1;
        sublists[1][i] = i+1+nn2*2;
        sublists[2][i] = i+1+nn2*3;
        sublists[3][i] = i+1+nn2;
    }

    //每个象限分别计算
    sublists[0] = magicOddBase(sublists[0], nn);
    sublists[1] = magicOddBase(sublists[1], nn);
    sublists[2] = magicOddBase(sublists[2], nn);
    sublists[3] = magicOddBase(sublists[3], nn);

    // 交换位置
    const nnList = _.range(0, nn);
    const kList = _.range(0, k);
    const k_1List = _.range(0, k-1);
    const mid = Math.floor(nn/2);
    _.forEach(nnList, o=>{
        let cr = o;
        let cc = (o===mid) ? mid-1 : -1;
        _.forEach(kList, i=>{
            cc++;
            swap(sublists[0], sublists[2], cr*nn+cc);
        });
        cc = mid-1;
        _.forEach(k_1List, i=>{
            cc++;
            swap(sublists[1], sublists[3], cr*nn+cc);
        });
    });

    // 合并四个象限
    const list = [];
    _.forEach(sublists[0], (o, i)=>{
        const row = Math.floor(i / nn);
        const col = i - row * nn;
        list[row*n+col] = sublists[0][i];
        list[row*n+col+nn] = sublists[1][i];
        list[(row+nn)*n+col] = sublists[2][i];
        list[(row+nn)*n+col+nn] = sublists[3][i];
    });

    return list;
}
function magicValidate(result, n) {
    const indexList = _.range(0, n);
    const rows = indexList.map(o=>result.slice(n*o, n*o+n));
    const cols = indexList.map(o=>indexList.map(p=>result[p*n+o]));
    const diagonals = [indexList.map(o=>result[o*n+o]), indexList.map(o=>result[o*n+n-1-o])];
    const list = rows.concat(cols).concat(diagonals).map(o=>_.sum(o));
    // console.log("====", list);
    const ret = _.every(list, o=>o===list[0]);
    console.log(ret ? '验证成功' : '验证失败');
}
function printResult(result, n) {
    const pn = Math.round(Math.log(n*n)*Math.LOG10E)+1;
    console.log(_.map(result, (o, i)=>(i+1)%n===0?(_.padStart(o, pn))+'\n':_.padStart(o, pn)+' ').join(''))
}
function showHelp() {
    console.log('Usage:');
    console.log('      xmagic num(>=3)');
    process.exit(0);
}
function main() {
    var args = process.argv.splice(2);
    const n = args[0]*1;
    if ( args[0] === '-h' ||  args[0]==='--help' || !(n>2) || !_.isInteger(n)) {
        showHelp();
    }
    const result = !(n & 3) ? magic4nTimes(n) : !(n & 1) ? magic4n2Times(n) : magicOdd(n);
    printResult(result, n);
    magicValidate(result, n);
}

main();
